home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000
/
Ham Radio 2000.iso
/
ham2000
/
tcp_ip
/
os2
/
pmnos11s
/
lapbtime.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-30
|
3KB
|
150 lines
/* LAPB (AX.25) timer recovery routines
* Copyright 1991 Phil Karn, KA9Q
*
* Mods by G1EMM
*/
#include "global.h"
#include "mbuf.h"
#include "ax25.h"
#include "timer.h"
#include "lapb.h"
static void tx_enq __ARGS((struct ax25_cb *axp));
int lapbtimertype = 0; /* default to binary exponential */
/* Called whenever timer T1 expires */
void
recover(p)
void *p;
{
register struct ax25_cb *axp = (struct ax25_cb *)p;
axp->flags.retrans = 1;
axp->retries++;
switch(lapbtimertype){
case 2: /* original backoff mode*/
set_timer(&axp->t1,axp->srt * 2);
break;
case 1: /* linear backoff mode */
if((1L << axp->retries) < Blimit)
set_timer(&axp->t1,dur_timer(&axp->t1) + axp->srt);
break;
case 0: /* exponential backoff mode */
if((1L << axp->retries) < Blimit)
set_timer(&axp->t1,dur_timer(&axp->t1)*2);
break;
}
switch(axp->state){
case LAPB_SETUP:
if(axp->n2 != 0 && axp->retries > axp->n2){
nr_derate(axp);
free_q(&axp->txq);
axp->reason = LB_TIMEOUT;
lapbstate(axp,LAPB_DISCONNECTED);
} else {
sendctl(axp,LAPB_COMMAND,SABM|PF);
start_timer(&axp->t1);
}
break;
case LAPB_DISCPENDING:
if(axp->n2 != 0 && axp->retries > axp->n2){
nr_derate(axp);
axp->reason = LB_TIMEOUT;
lapbstate(axp,LAPB_DISCONNECTED);
} else {
sendctl(axp,LAPB_COMMAND,DISC|PF);
start_timer(&axp->t1);
}
break;
case LAPB_CONNECTED:
case LAPB_RECOVERY:
if(axp->n2 != 0 && axp->retries > axp->n2){
/* Give up */
nr_derate(axp);
sendctl(axp,LAPB_RESPONSE,DM|PF);
free_q(&axp->txq);
axp->reason = LB_TIMEOUT;
lapbstate(axp,LAPB_DISCONNECTED);
} else {
/* Transmit poll */
tx_enq(axp);
lapbstate(axp,LAPB_RECOVERY);
}
break;
}
}
/* Send a poll (S-frame command with the poll bit set) */
void
pollthem(p)
void *p;
{
register struct ax25_cb *axp;
axp = (struct ax25_cb *)p;
if(axp->proto == V1)
return; /* Not supported in the old protocol */
switch(axp->state){
case LAPB_CONNECTED:
axp->retries = 0;
tx_enq(axp);
lapbstate(axp,LAPB_RECOVERY);
break;
}
}
/* Called whenever timer T4 (link rudundancy timer) expires */
void
redundant(p)
void *p;
{
register struct ax25_cb *axp;
axp = (struct ax25_cb *)p;
switch(axp->state){
case LAPB_CONNECTED:
case LAPB_RECOVERY:
axp->retries = 0;
sendctl(axp,LAPB_COMMAND,DISC|PF);
start_timer(&axp->t1);
free_q(&axp->txq);
lapbstate(axp,LAPB_DISCPENDING);
break;
}
}
/* Transmit query */
static void
tx_enq(axp)
register struct ax25_cb *axp;
{
char ctl;
struct mbuf *bp;
/* I believe that retransmitting the oldest unacked
* I-frame tends to give better performance than polling,
* as long as the frame isn't too "large", because
* chances are that the I frame got lost anyway.
* This is an option in LAPB, but not in the official AX.25.
*/
if(axp->txq != NULLBUF
&& (len_p(axp->txq) < axp->pthresh || axp->proto == V1)){
/* Retransmit oldest unacked I-frame */
dup_p(&bp,axp->txq,0,len_p(axp->txq));
ctl = PF | I | (((axp->vs - axp->unack) & MMASK) << 1)
| (axp->vr << 5);
sendframe(axp,LAPB_COMMAND,ctl,bp);
} else {
ctl = len_p(axp->rxq) >= axp->window ? RNR|PF : RR|PF;
sendctl(axp,LAPB_COMMAND,ctl);
}
axp->response = 0;
stop_timer(&axp->t3);
start_timer(&axp->t1);
}